<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8" />
    <title>1.类的基本知识</title>
</head>

<body>
    <script type="text/javascript">
        /*****
         * 总结
         * 1,类中的构造器不是必须要写的,要对实例进行初始化操的作,如添加指定属性时才写.
         * 2,如果A类继承了B类,且A类中写了构造器,那么A类中的构造器super中是必须要调用的.
         * 3,类中所定义的方法,都是放在子类的原型对象上,供实例使用  
         * 
         * ********/
        //创建一个Person类
        class Person {
            //构造器方法
            constructor(name, age) {
                //构造器中的this指的是谁,? 类的实例对象  
                this.name = name;
                this.age = age;
                // console.log("构造器中的this指的是", this)
            }
            //一般方法
            speak() {
                //speak方法放在哪里?--Person类的原型对象上,供实例使用
                // 通过Person实例调用speak时,speak中的this就是Persion实例
                console.log(`我叫${this.name},我的年龄是${this.age}`)
            }
        }
        // //创建person类的实例对象
        // const p1 = new Person("tom", 18);
        // const p2 = new Person('marry', 20);
        // p1.speak();
        // p2.speak()
        // console.log(p1)
        // console.log(p2)
        //创建是一个 Student类,继承Person类
        class Student extends Person {
            //若是子类属性和父类属性一致,可以不用写子类构造器constructor方法,
            //但是子类有父类没有的属性"高一",需要接收子类独有的属性所以要写constructor方法,
            //接收子类独有的属性
            constructor(name, age, grade) {
                /**
                 * 没有调用super()方法时会报错
                 * this.name = name;
                this.age = age;*
                1.类的基本知识.html:41 Uncaught 
                ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
                    at new Student (1.类的基本知识.html:41:17)
                    at 1.类的基本知识.html:46:20               
                **/
                //调用super()
                super(name, age); //调用父类的构造器,接收子类和父类共同都有的属性 必须写在最前面调用(第一行)
                this.grade = grade;
            }
            //重写父类原型上的speak方法
            speak() {
                console.log(`我的名字是${this.name},我的年龄是${this.age},我的读的是${this.grade}年级`)
            }
            study() {
                //studay方法放在哪里?--Student类的原型对象上,供实例(s1)使用
                // 通过Student实例调用study时(s1.study()),study中的this就是Student实例(即s1)
                console.log("我很努力的学习")
            }

        }
        const s1 = new Student('小张', 15, '高一')
        console.log(s1)
        s1.speak()
        s1.study()

        class Car {
            constructor(name, price) {
                this.name = name;
                this.price = price;
            }
            //类中可以直接写赋值语句,如下代码的含义是:给Car的实例对象添加一个属性,名为a,值为1
            a = 1;
            wheel = 4; //轮子4个
            //普通函数放在实例原型上
            // run() {

            // }
            //赋值成将头函数放在实例自身的上
            run = () => {

            }
        }
        const c1 = new Car('奔驰c63', 199)
        const c2 = new Car('宝马', 200)
        console.log(c1)
        console.log(c2)
    </script>
</body>

</html>